μΉ μ ν리μΌμ΄μ μ μν κ°λ ₯ν νλ‘ νΈμλ 곡μ λμ νλ‘μΈμλ₯Ό ꡬμΆνκΈ° μν ν¬κ΄μ μΈ κ°μ΄λλ‘, λ°μ΄ν° κ΄λ¦¬, 보μ λ° κ³΅μ μ½ν μΈ μ²λ¦¬λ₯Ό μν λͺ¨λ² μ¬λ‘λ₯Ό λ€λ£Ήλλ€.
νλ‘ νΈμλ μΉ κ³΅μ λμ νλ‘μΈμ: 곡μ λ°μ΄ν° κ΄λ¦¬ λ§μ€ν°νκΈ°
Web Share Target APIλ νλ‘κ·Έλ μλΈ μΉ μ±(PWA) λ° μΉ μ ν리μΌμ΄μ μ ν₯λ―Έλ‘μ΄ κ°λ₯μ±μ μ΄μ΄ μ¬μ©μκ° λ€λ₯Έ μ±μμ μ§μ μ ν리μΌμ΄μ μΌλ‘ μ½ν μΈ λ₯Ό μννκ² κ³΅μ ν μ μλλ‘ ν©λλ€. μ΄ κΈ°λ₯μ μ¬μ©μ μ°Έμ¬λ₯Ό ν₯μμν€κ³ λ λΆλλ½κ³ ν΅ν©λ κ²½νμ μ 곡ν©λλ€. κ·Έλ¬λ νλ‘ νΈμλμμ 곡μ λ°μ΄ν°λ₯Ό ν¨κ³Όμ μΌλ‘ μ²λ¦¬νλ €λ©΄ μ μ€ν κ³ν, κ°λ ₯ν μ€λ₯ μ²λ¦¬, 보μμ λν μ§μ€μ΄ νμν©λλ€. μ΄ ν¬κ΄μ μΈ κ°μ΄λλ κ°λ ₯νκ³ μμ ν νλ‘ νΈμλ 곡μ λμ νλ‘μΈμλ₯Ό ꡬμΆνλ κ³Όμ μ μλ΄ν©λλ€.
Web Share Target API μ΄ν΄νκΈ°
ꡬνμ μμνκΈ° μ μ Web Share Target APIμ λν΄ κ°λ΅νκ² μ΄ν΄λ³΄κ² μ΅λλ€. μ΄λ λ³Έμ§μ μΌλ‘ μΉ μ ν리μΌμ΄μ μ΄ μ΄μ 체μ μ μ체μ μΌλ‘ 곡μ λμμΌλ‘ λ±λ‘ν μ μλλ‘ ν©λλ€. μ¬μ©μκ° λ€λ₯Έ μ ν리μΌμ΄μ μμ μ½ν μΈ (μ: ν μ€νΈ, URL, νμΌ)λ₯Ό 곡μ νλ €λ κ²½μ° PWAκ° κ³΅μ μνΈμμ μ΅μ μΌλ‘ λνλ©λλ€.
곡μ λμμ νμ±ννλ €λ©΄ μΉ μ± λ§€λνμ€νΈ(manifest.json) λ΄μμ μ μν΄μΌ ν©λλ€. μ΄ λ§€λνμ€νΈλ λΈλΌμ°μ μ λ€μ΄μ€λ 곡μ μμ²μ μ²λ¦¬νλ λ°©λ²μ μλ €μ€λλ€. λ€μμ κΈ°λ³Έ μμ
λλ€.
{
"name": "My Awesome App",
"short_name": "Awesome App",
"start_url": "/",
"display": "standalone",
"background_color": "#fff",
"theme_color": "#000",
"icons": [
{
"src": "icon.png",
"sizes": "512x512",
"type": "image/png"
}
],
"share_target": {
"action": "/share-target",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"title": "title",
"text": "text",
"url": "url",
"files": [
{
"name": "sharedFiles",
"accept": ["image/*", "video/*"]
}
]
}
}
}
ν΅μ¬ μμλ₯Ό μμΈν μ΄ν΄λ³΄κ² μ΅λλ€.
action: 곡μ λ°μ΄ν°λ₯Ό μ²λ¦¬ν PWA λ΄μ URLμ λλ€. μ΄ URLμ μ¬μ©μκ° μ±μ μ½ν μΈ λ₯Ό 곡μ ν λ νΈμΆλ©λλ€.method: λ°μ΄ν°λ₯Ό μ μ‘νλ λ° μ¬μ©λλ HTTP λ©μλμ λλ€. μΌλ°μ μΌλ‘ 곡μ λμμλPOSTλ₯Ό μ¬μ©ν©λλ€.enctype: λ°μ΄ν°μ μΈμ½λ© μ νμ λλ€.multipart/form-dataλ μΌλ°μ μΌλ‘ νμΌμ μ²λ¦¬νλ λ° μ ν©νλ©°application/x-www-form-urlencodedλ λ κ°λ¨ν ν μ€νΈ κΈ°λ° λ°μ΄ν°μ μ¬μ©ν μ μμ΅λλ€.params: 곡μ λ°μ΄ν°κ° μμ νλμ λ§€νλλ λ°©μμ μ μν©λλ€. μ΄λ₯Ό ν΅ν΄ 곡μ λλ μ λͺ©, ν μ€νΈ, URL λ° νμΌμ μ½κ² μ‘μΈμ€ν μ μμ΅λλ€.
μ¬μ©μκ° κ³΅μ μνΈμμ μ±μ μ ννλ©΄ λΈλΌμ°μ λ action URLλ‘ μ΄λνμ¬ κ³΅μ λ°μ΄ν°λ₯Ό POST μμ²μΌλ‘ 보λ
λλ€.
νλ‘ νΈμλ 곡μ λμ νλ‘μΈμ ꡬμΆνκΈ°
곡μ λμ νλ‘μΈμμ ν΅μ¬μ μ§μ λ action URLμμ λ€μ΄μ€λ λ°μ΄ν°λ₯Ό μ²λ¦¬νλ JavaScript μ½λμ μμ΅λλ€. μ¬κΈ°μμ 곡μ μ½ν
μΈ λ₯Ό μΆμΆνκ³ , μ ν¨μ±μ κ²μ¬νκ³ , μ μ νκ² μ²λ¦¬ν©λλ€.
1. μλΉμ€ μ컀 κ°λ‘μ±κΈ°
곡μ λμ λ°μ΄ν°λ₯Ό μ²λ¦¬νλ κ°μ₯ μμ μ μΈ λ°©λ²μ μλΉμ€ μ컀λ₯Ό μ¬μ©νλ κ²μ λλ€. μλΉμ€ μ컀λ κΈ°λ³Έ μ ν리μΌμ΄μ μ€λ λμ λ 립μ μΌλ‘ λ°±κ·ΈλΌμ΄λμμ μ€νλλ©° 곡μ λμμμ νΈλ¦¬κ±°λ POST μμ²μ ν¬ν¨νμ¬ λ€νΈμν¬ μμ²μ κ°λ‘μ± μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μ ν리μΌμ΄μ μ΄ ν¬κ·ΈλΌμ΄λμμ νμ±μΌλ‘ μ€νλμ§ μλ κ²½μ°μλ 곡μ μμ²μ μ²λ¦¬ν μ μμ΅λλ€.
λ€μμ 곡μ λμ μμ²μ κ°λ‘μ±λ μλΉμ€ μ컀μ κΈ°λ³Έ μμ λλ€.
// service-worker.js
self.addEventListener('fetch', event => {
if (event.request.method === 'POST' && event.request.url.includes('/share-target')) {
event.respondWith(handleShareTarget(event));
}
});
async function handleShareTarget(event) {
const formData = await event.request.formData();
// FormData κ°μ²΄μμ λ°μ΄ν° μΆμΆ
const title = formData.get('title');
const text = formData.get('text');
const url = formData.get('url');
const files = formData.getAll('sharedFiles');
// 곡μ λ°μ΄ν° μ²λ¦¬
console.log('Title:', title);
console.log('Text:', text);
console.log('URL:', url);
console.log('Files:', files);
// μμ²μ μλ΅ (μ: νμΈ νμ΄μ§λ‘ 리λλ μ
)
return Response.redirect('/confirmation');
}
μ΄ μλΉμ€ μ컀μ μ£Όμ μ¬ν:
fetchμ΄λ²€νΈ 리μ€λ: λͺ¨λ λ€νΈμν¬ μμ²μ μμ λκΈ°ν©λλ€.- μμ² νν°λ§: μμ²μ΄
POSTμμ²μ΄κ³ URLμ/share-targetκ° ν¬ν¨λμ΄ μλμ§ νμΈν©λλ€. μ΄λ κ² νλ©΄ 곡μ λμ μμ²λ§ κ°λ‘μ±μ§λλ€. event.respondWith(): λΈλΌμ°μ κ° μμ²μ μ μμ μΌλ‘ μ²λ¦¬νλ κ²μ λ°©μ§νκ³ μλΉμ€ μμ»€κ° μ¬μ©μ μ§μ μλ΅μ μ 곡ν μ μλλ‘ ν©λλ€.handleShareTarget(): 곡μ λ°μ΄ν°λ₯Ό μ²λ¦¬νλ λΉλκΈ° ν¨μμ λλ€.event.request.formData(): POST μμ² λ³Έλ¬ΈμFormDataκ°μ²΄λ‘ ꡬ문 λΆμνμ¬ κ³΅μ λ°μ΄ν°μ μ½κ² μ‘μΈμ€ν μ μλλ‘ ν©λλ€.- λ°μ΄ν° μΆμΆ: μ½λλ
formData.get()λ°formData.getAll()μ μ¬μ©νμ¬FormDataκ°μ²΄μμ μ λͺ©, ν μ€νΈ, URL λ° νμΌμ μΆμΆν©λλ€. - λ°μ΄ν° μ²λ¦¬: μμ μ½λλ λ¨μν λ°μ΄ν°λ₯Ό μ½μμ κΈ°λ‘ν©λλ€. μ€μ μ ν리μΌμ΄μ μμλ λ°μ΄ν°λ₯Ό λ μ²λ¦¬ν©λλ€(μ: λ°μ΄ν°λ² μ΄μ€μ μ μ₯, UIμ νμ).
- μλ΅: μ½λλ μ¬μ©μλ₯Ό νμΈ νμ΄μ§λ‘ 리λλ μ νμ¬ μμ²μ μλ΅ν©λλ€. νμμ λ°λΌ μλ΅μ μ¬μ©μ μ§μ ν μ μμ΅λλ€.
μ€μ: μλΉμ€ μμ»€κ° κΈ°λ³Έ JavaScript μ½λμ μ λλ‘ λ±λ‘λμλμ§ νμΈνμμμ€. κ°λ¨ν λ±λ‘ μ€λν«μ λ€μκ³Ό κ°μ΅λλ€.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
}
2. λ°μ΄ν° μΆμΆ λ° μ ν¨μ± κ²μ¬
곡μ λμ μμ²μ κ°λ‘μ± ν λ€μ λ¨κ³λ FormData κ°μ²΄μμ λ°μ΄ν°λ₯Ό μΆμΆνκ³ μ ν¨μ±μ κ²μ¬νλ κ²μ
λλ€. μ΄λ λ°μ΄ν° 무결μ±μ 보μ₯νκ³ λ³΄μ μ·¨μ½μ±μ λ°©μ§νλ λ° λ§€μ° μ€μν©λλ€.
λ€μμ 곡μ λ°μ΄ν°λ₯Ό μΆμΆνκ³ μ ν¨μ±μ κ²μ¬νλ λ°©λ²μ μμ λλ€.
async function handleShareTarget(event) {
const formData = await event.request.formData();
const title = formData.get('title');
const text = formData.get('text');
const url = formData.get('url');
const files = formData.getAll('sharedFiles');
// λ°μ΄ν° μ ν¨μ± κ²μ¬
if (!title) {
console.error('Title is missing.');
return new Response('Title is required.', { status: 400 });
}
if (files && files.length > 0) {
for (const file of files) {
if (file.size > 10 * 1024 * 1024) { // νμΌ ν¬κΈ°λ₯Ό 10MBλ‘ μ ν
console.error('File size exceeds limit.');
return new Response('File size exceeds limit (10MB).', { status: 400 });
}
if (!file.type.startsWith('image/') && !file.type.startsWith('video/')) {
console.error('Invalid file type.');
return new Response('Invalid file type. Only images and videos are allowed.', { status: 400 });
}
}
}
// (μ ν¨μ± κ²μ¬μ ν΅κ³Όνλ κ²½μ°) 곡μ λ°μ΄ν° μ²λ¦¬
console.log('Title:', title);
console.log('Text:', text);
console.log('URL:', url);
console.log('Files:', files);
// μμ²μ μλ΅
return Response.redirect('/confirmation');
}
μ΄ μμμλ λ€μ μ ν¨μ± κ²μ¬λ₯Ό 보μ¬μ€λλ€.
- νμ νλ: μ λͺ©μ΄ μλμ§ νμΈν©λλ€. κ·Έλ μ§ μμ κ²½μ° μ€λ₯ μλ΅μ λ°νν©λλ€.
- νμΌ ν¬κΈ° μ ν: μ΅λ νμΌ ν¬κΈ°λ₯Ό 10MBλ‘ μ νν©λλ€. μ΄λ μλΉμ€ κ±°λΆ κ³΅κ²©μ λ°©μ§νκ³ μλ²κ° ν° νμΌλ‘ κ³ΌλΆνλμ§ μλλ‘ νλ λ° λμμ΄ λ©λλ€.
- νμΌ νμ μ ν¨μ± κ²μ¬: μ΄λ―Έμ§ λ° λΉλμ€ νμΌλ§ νμ©ν©λλ€. μ΄λ μ¬μ©μκ° μ μ± νμΌμ μ λ‘λνλ κ²μ λ°©μ§νλ λ° λμμ΄ λ©λλ€.
μ ν리μΌμ΄μ μ νΉμ μꡬ μ¬νμ λ°λΌ μ΄λ¬ν μ ν¨μ± κ²μ¬λ₯Ό μ¬μ©μ μ§μ νλ κ²μ μμ§ λ§μμμ€. URL νμ, ν μ€νΈ κΈΈμ΄ λ° κΈ°ν κ΄λ ¨ λ§€κ°λ³μμ λν μ ν¨μ± κ²μ¬λ₯Ό μΆκ°νλ κ²μ κ³ λ €νμμμ€.
3. 곡μ νμΌ μ²λ¦¬
곡μ νμΌμ μ²λ¦¬ν λλ ν¨μ¨μ μ΄κ³ μμ νκ² μ²λ¦¬νλ κ²μ΄ μ€μν©λλ€. λ€μμ λͺ κ°μ§ λͺ¨λ² μ¬λ‘μ λλ€.
- νμΌ λ΄μ© μ½κΈ°:
FileReaderAPIλ₯Ό μ¬μ©νμ¬ κ³΅μ νμΌμ λ΄μ©μ μ½μ΅λλ€. - νμΌ μμ νκ² μ μ₯: μ μ ν μ‘μΈμ€ μ μ΄λ₯Ό μ¬μ©νμ¬ μλ²μ μμ ν μμΉμ νμΌμ μ μ₯ν©λλ€. νμ₯μ± λ° λ³΄μμ μν΄ Amazon S3, Google Cloud Storage λλ Azure Blob Storageμ κ°μ ν΄λΌμ°λ μ€ν λ¦¬μ§ μλΉμ€λ₯Ό μ¬μ©νλ κ²μ κ³ λ €νμμμ€.
- κ³ μ ν νμΌ μ΄λ¦ μμ±: μ΄λ¦ μΆ©λ λ° μ μ¬μ μΈ λ³΄μ μ·¨μ½μ±μ λ°©μ§νκΈ° μν΄ κ³ μ ν νμΌ μ΄λ¦μ μμ±ν©λλ€. νμμ€ν¬ν, μμμ μ«μ λ° μ¬μ©μ IDλ₯Ό κ²°ν©νμ¬ κ³ μ ν νμΌ μ΄λ¦μ λ§λ€ μ μμ΅λλ€.
- νμΌ μ΄λ¦ μ 리: μ μ¬μ μΌλ‘ μ μμ μΈ λ¬Έμλ₯Ό μ κ±°νκΈ° μν΄ νμΌ μ΄λ¦μ μ 리ν©λλ€. μ΄λ μ¬μ΄νΈ κ° μ€ν¬λ¦½ν (XSS) μ·¨μ½μ±μ λ°©μ§νλ λ° λμμ΄ λ©λλ€.
- Content Security Policy(CSP): Content Security Policy(CSP)λ₯Ό ꡬμ±νμ¬ μ ν리μΌμ΄μ μμ λ‘λν μ μλ 리μμ€ μ νμ μ νν©λλ€. μ΄λ 곡격μκ° μ μ± μ½λλ₯Ό μ ν리μΌμ΄μ μ μ½μ νλ κΈ°λ₯μ μ ννμ¬ XSS 곡격μ λ°©μ§νλ λ° λμμ΄ λ©λλ€.
λ€μμ FileReader APIλ₯Ό μ¬μ©νμ¬ κ³΅μ νμΌμ λ΄μ©μ μ½λ λ°©λ²μ μμ
λλ€.
async function processFiles(files) {
for (const file of files) {
const reader = new FileReader();
reader.onload = (event) => {
const fileData = event.target.result;
console.log('File data:', fileData);
// μ΄μ fileDataλ₯Ό μμ νκ² μ
λ‘λνκ±°λ μ μ₯ν μ μμ΅λλ€.
};
reader.onerror = (error) => {
console.error('Error reading file:', error);
};
reader.readAsDataURL(file); // λλ λ°μ΄λ리 λ°μ΄ν°μ κ²½μ° readAsArrayBuffer
}
}
μ΄ μ½λλ 곡μ νμΌμ λ°λ³΅νκ³ FileReaderλ₯Ό μ¬μ©νμ¬ κ° νμΌμ λ°μ΄ν°λ₯Ό μ½μ΅λλ€. νμΌμ΄ μ±κ³΅μ μΌλ‘ μ½νλ©΄ onload μ΄λ²€νΈ μ²λ¦¬κΈ°κ° νΈμΆλκ³ fileData λ³μμλ λ°μ΄ν° URLλ‘ νμΌμ λ΄μ©μ΄ ν¬ν¨λ©λλ€(readAsArrayBufferλ₯Ό μ¬μ©νλ κ²½μ° ArrayBuffer). κ·Έλ° λ€μ μ΄ λ°μ΄ν°λ₯Ό μλ²μ μ
λ‘λνκ±°λ λ‘컬 λ°μ΄ν°λ² μ΄μ€μ μ μ₯ν μ μμ΅λλ€.
4. λ€μν λ°μ΄ν° μ ν μ²λ¦¬
Web Share Target APIλ ν μ€νΈ, URL λ° νμΌμ ν¬ν¨ν λ€μν λ°μ΄ν° μ νμ μ²λ¦¬ν μ μμ΅λλ€. 곡μ λμ νλ‘μΈμλ μ΄λ¬ν κ° λ°μ΄ν° μ νμ μ μ νκ² μ²λ¦¬ν μ μμ΄μΌ ν©λλ€.
- ν
μ€νΈ: ν
μ€νΈ λ°μ΄ν°μ κ²½μ°
FormDataκ°μ²΄μμ ν μ€νΈλ₯Ό μΆμΆνκ³ νμμ λ°λΌ μ²λ¦¬ν μ μμ΅λλ€. μλ₯Ό λ€μ΄, ν μ€νΈλ₯Ό λ°μ΄ν°λ² μ΄μ€μ μ μ₯νκ±°λ, UIμ νμνκ±°λ, κ²μμ μννλ λ° μ¬μ©ν μ μμ΅λλ€. - URL: URLμ κ²½μ° URL νμμ νμΈνκ³ μ΄λνκΈ°μ μμ νμ§ νμΈν΄μΌ ν©λλ€. μ κ·μ λλ URL ꡬ문 λΆμ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ URLμ μ ν¨μ±μ κ²μ¬ν μ μμ΅λλ€.
- νμΌ: μμ μ€λͺ ν λλ‘ νμΌμ 보μμ 보μ₯νκ³ λ°μ΄ν° μμ€μ λ°©μ§νκΈ° μν΄ μ£Όμν΄μ μ²λ¦¬ν΄μΌ ν©λλ€. νμΌ μ ν λ° ν¬κΈ°μ μ ν¨μ±μ κ²μ¬νκ³ μ λ‘λλ νμΌμ μ μ ν μ‘μΈμ€ μ μ΄ κΈ°λ₯μΌλ‘ μμ νκ² μ μ₯νμμμ€.
5. μ¬μ©μμκ² νΌλλ°± νμ
곡μ μμ μ μνμ λν νΌλλ°±μ μ¬μ©μμκ² μ 곡νλ κ²μ΄ μ€μν©λλ€. μ±κ³΅ λ©μμ§, μ€λ₯ λ©μμ§ λλ λ‘λ© νμκΈ°λ₯Ό νμνμ¬ μ΄λ₯Ό μνν μ μμ΅λλ€.
- μ±κ³΅ λ©μμ§: 곡μ μμ μ΄ μ±κ³΅μ μΌλ‘ μλ£λλ©΄ μ±κ³΅ λ©μμ§λ₯Ό νμν©λλ€. μλ₯Ό λ€μ΄ "μ½ν μΈ κ° μ±κ³΅μ μΌλ‘ 곡μ λμμ΅λλ€!"λΌλ λ©μμ§λ₯Ό νμν μ μμ΅λλ€.
- μ€λ₯ λ©μμ§: 곡μ μμ μ΄ μ€ν¨νλ©΄ μ€λ₯ λ©μμ§λ₯Ό νμν©λλ€. μ¬μ©μκ° λ¬΄μμ΄ μλͺ»λμλμ§ μ΄ν΄νκ³ ν΄κ²°νλ λ° λμμ΄ λλ λͺ ννκ³ μ μ΅ν μ€λ₯ λ©μμ§λ₯Ό μ 곡ν©λλ€. μλ₯Ό λ€μ΄ "μ½ν μΈ λ₯Ό 곡μ νμ§ λͺ»νμ΅λλ€. λμ€μ λ€μ μλνμμμ€."λΌλ λ©μμ§λ₯Ό νμν μ μμ΅λλ€. μ¬μ© κ°λ₯ν κ²½μ° νΉμ μΈλΆ μ 보λ₯Ό ν¬ν¨ν©λλ€(μ: "νμΌ ν¬κΈ°κ° μ νμ μ΄κ³Όνμ΅λλ€.").
- λ‘λ© νμκΈ°: 곡μ μμ μ΄ μ§ν μ€μΌ λ λ‘λ© νμκΈ°λ₯Ό νμν©λλ€. μ΄λ₯Ό ν΅ν΄ μ¬μ©μλ μ ν리μΌμ΄μ μ΄ μλ μ€μμ μ μ μμΌλ©° μμ μ΄ μλ£λ λκΉμ§ λ μ΄μμ μμ μ μννμ§ λͺ»νκ² λ©λλ€.
JavaScriptλ₯Ό μ¬μ©νμ¬ μ΄λ¬ν λ©μμ§λ₯Ό νμνλλ‘ UIλ₯Ό λμ μΌλ‘ μ λ°μ΄νΈν μ μμ΅λλ€. λ°©ν΄λ°μ§ μλ λ©μμ§λ₯Ό μ¬μ©μμκ² νμνλ €λ©΄ μλ¦Ό λΌμ΄λΈλ¬λ¦¬ λλ ν μ€νΈ κ΅¬μ± μμλ₯Ό μ¬μ©νλ κ²μ κ³ λ €νμμμ€.
6. 보μ κ³ λ € μ¬ν
곡μ λμ νλ‘μΈμλ₯Ό ꡬμΆν λ 보μμ΄ κ°μ₯ μ€μν©λλ€. λ€μμ λͺ κ°μ§ μ£Όμ 보μ κ³ λ € μ¬νμ λλ€.
- λ°μ΄ν° μ ν¨μ± κ²μ¬: μ£Όμ 곡격 λ° κΈ°ν 보μ μ·¨μ½μ μ λ°©μ§νλ €λ©΄ νμ λͺ¨λ λ€μ΄μ€λ λ°μ΄ν°μ μ ν¨μ±μ κ²μ¬ν©λλ€. λ°μ΄ν°μ νμ, μ ν λ° ν¬κΈ°μ μ ν¨μ±μ κ²μ¬νκ³ μ μ¬μ μΌλ‘ μ μμ μΈ λ¬Έμλ₯Ό μ 리ν©λλ€.
- μ¬μ΄νΈ κ° μ€ν¬λ¦½ν (XSS): UIμ νμλλ λͺ¨λ μ¬μ©μ μ 곡 λ°μ΄ν°λ₯Ό μ΄μ€μΌμ΄ννμ¬ XSS 곡격μΌλ‘λΆν° 보νΈν©λλ€. HTML μν°ν°λ₯Ό μλμΌλ‘ μ΄μ€μΌμ΄ννλ ν νλ¦Ώ μμ§μ μ¬μ©νκ±°λ μ μ© XSS λ³΄νΈ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν©λλ€.
- μ¬μ΄νΈ κ° μμ² μμ‘°(CSRF): CSRF ν ν°μ μ¬μ©νμ¬ CSRF 곡격μΌλ‘λΆν° 보νΈν©λλ€. CSRF ν ν°μ μλ²μμ μμ±λμ΄ λͺ¨λ μμ λ° AJAX μμ²μ ν¬ν¨λ κ³ μ νκ³ μμΈ‘ν μ μλ κ°μ λλ€. μ΄λ₯Ό ν΅ν΄ 곡격μκ° μΈμ¦λ μ¬μ©μλ₯Ό λμ νμ¬ μμ²μ μμ‘°νλ κ²μ λ°©μ§ν μ μμ΅λλ€.
- νμΌ μ λ‘λ 보μ: μ¬μ©μκ° μ μ± νμΌμ μ λ‘λνμ§ λͺ»νλλ‘ κ°λ ₯ν νμΌ μ λ‘λ 보μ μ‘°μΉλ₯Ό ꡬνν©λλ€. νμΌ νμ, νμΌ ν¬κΈ° λ° νμΌ λ΄μ©μ μ ν¨μ±μ κ²μ¬νκ³ μ λ‘λλ νμΌμ μ μ ν μ‘μΈμ€ μ μ΄ κΈ°λ₯μΌλ‘ μμ ν μμΉμ μ μ₯ν©λλ€.
- HTTPS: μ ν리μΌμ΄μ κ³Ό μλ² κ°μ λͺ¨λ ν΅μ μ μνΈννλ €λ©΄ νμ HTTPSλ₯Ό μ¬μ©ν©λλ€. μ΄λ 곡격μκ° λ―Όκ°ν λ°μ΄ν°λ₯Ό λμ²νλ κ²μ λ°©μ§ν©λλ€.
- Content Security Policy(CSP): CSPλ₯Ό ꡬμ±νμ¬ μ ν리μΌμ΄μ μμ λ‘λν μ μλ 리μμ€ μ νμ μ νν©λλ€. μ΄λ 곡격μκ° μ μ± μ½λλ₯Ό μ ν리μΌμ΄μ μ μ½μ νλ κΈ°λ₯μ μ ννμ¬ XSS 곡격μ λ°©μ§νλ λ° λμμ΄ λ©λλ€.
- μ κΈ° 보μ κ°μ¬: μ μ¬μ μΈ λ³΄μ μ·¨μ½μ μ μλ³νκ³ μμ νκΈ° μν΄ μ κΈ°μ μΌλ‘ 보μ κ°μ¬λ₯Ό μνν©λλ€. μλνλ 보μ κ²μ¬ λꡬλ₯Ό μ¬μ©νκ³ λ³΄μ μ λ¬Έκ°μ νλ ₯νμ¬ μ ν리μΌμ΄μ μ 보μμ 보μ₯ν©λλ€.
μ λ° μ¬μ© μ¬λ‘
λ€μμ Web Share Target APIλ₯Ό μ€μ μ ν리μΌμ΄μ μμ μ¬μ©ν μ μλ λͺ κ°μ§ μμ λλ€.
- μμ λ―Έλμ΄ μ±: μ¬μ©μκ° λ€λ₯Έ μ±μμ μ§μ μμ λ―Έλμ΄ νλ«νΌμΌλ‘ μ½ν μΈ λ₯Ό 곡μ νλλ‘ νμ©ν©λλ€. μλ₯Ό λ€μ΄, μ¬μ©μλ λ΄μ€ μ±μμ μμ λ―Έλμ΄ μ±μΌλ‘ 미리 μ±μμ§ λ©μμ§μ ν¨κ» λ§ν¬λ₯Ό 곡μ ν μ μμ΅λλ€.
- λ ΈνΈ μμ± μ±: μ¬μ©μκ° λ€λ₯Έ μ±μμ ν μ€νΈ, URL λ° νμΌμ λ ΈνΈ μμ± μ±μΌλ‘ μ§μ 곡μ νλλ‘ νμ©ν©λλ€. μλ₯Ό λ€μ΄, μ¬μ©μλ μ½λ νΈμ§κΈ°μμ λ ΈνΈ μμ± μ±μΌλ‘ μ½λ μ‘°κ°μ 곡μ ν μ μμ΅λλ€.
- μ΄λ―Έμ§ νΈμ§ μ±: μ¬μ©μκ° λ€λ₯Έ μ±μμ μ΄λ―Έμ§λ₯Ό μ΄λ―Έμ§ νΈμ§ μ±μΌλ‘ μ§μ 곡μ νλλ‘ νμ©ν©λλ€. μλ₯Ό λ€μ΄, μ¬μ©μλ μ¬μ§ κ°€λ¬λ¦¬ μ±μμ μ΄λ―Έμ§ νΈμ§ μ±μΌλ‘ μ¬μ§μ 곡μ ν μ μμ΅λλ€.
- μ μ μκ±°λ μ±: μ¬μ©μκ° λ€λ₯Έ μ±μμ μ νμ μ μ μκ±°λ μ±μΌλ‘ μ§μ 곡μ νλλ‘ νμ©ν©λλ€. μλ₯Ό λ€μ΄, μ¬μ©μλ μΌν μ±μμ μ μ μκ±°λ μ±μΌλ‘ μ νμ 곡μ νμ¬ κ°κ²©μ λΉκ΅ν μ μμ΅λλ€.
- νμ λꡬ: μ¬μ©μκ° λ€λ₯Έ μ±μμ λ¬Έμ λ° νμΌμ νμ λκ΅¬λ‘ μ§μ 곡μ νλλ‘ νμ©ν©λλ€. μλ₯Ό λ€μ΄, μ¬μ©μλ λ¬Έμ νΈμ§κΈ° μ±μμ νμ λκ΅¬λ‘ λ¬Έμλ₯Ό 곡μ νμ¬ κ²ν ν μ μμ΅λλ€.
κΈ°λ³Έ μ¬ν μ΄μ: κ³ κΈ κΈ°μ
κΈ°λ³Έ 곡μ λμ νλ‘μΈμλ₯Ό κ°μΆ νμλ λͺ κ°μ§ κ³ κΈ κΈ°μ μ νμνμ¬ κΈ°λ₯μ ν₯μμν¬ μ μμ΅λλ€.
- μ¬μ©μ μ§μ 곡μ μνΈ: νμ€ κ³΅μ μνΈλ μ΄μ 체μ μμ μ 곡λ©λλ€. κ·Έλ¬λ νλ«νΌ λ° κ³΅μ κΈ°λ₯μ λ°λΌ μ¬μ©μ μ§μ μμλ₯Ό μ¬μ©νμ¬ κ³΅μ μνΈ κ²½νμ μν₯μ λ―ΈμΉκ±°λ μ΄λ₯Ό 보κ°ν μ μμ΅λλ€. νλ«νΌ μ νμΌλ‘ μΈν΄ μ¬μ©μ μ§μ μ λκ° μ νλ μ μμμ μΈμ§νμμμ€.
- μ μ§μ κ°μ : 곡μ λμ κΈ°λ₯μ μ μ§μ κ°μ μΌλ‘ ꡬνν©λλ€. Web Share Target APIκ° λΈλΌμ°μ μμ μ§μλμ§ μλ κ²½μ° κ³΅μ λμ κΈ°λ₯μ΄ μλλΌλ μ ν리μΌμ΄μ μ΄ μ¬μ ν μ λλ‘ μλν΄μΌ ν©λλ€.
- μ§μ°λ μ²λ¦¬: 볡μ‘ν μ²λ¦¬ μμ μ κ²½μ° μ²λ¦¬λ₯Ό λ°±κ·ΈλΌμ΄λ μμ μΌλ‘ μ°κΈ°νλ κ²μ κ³ λ €νμμμ€. μ΄λ κ² νλ©΄ μ ν리μΌμ΄μ μ μλ΅μ±μ κ°μ νκ³ UIκ° λ©μΆλ κ²μ λ°©μ§ν μ μμ΅λλ€. λ°±κ·ΈλΌμ΄λ ν λλ μ μ© λ°±κ·ΈλΌμ΄λ μ²λ¦¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μ΄λ¬ν μμ μ κ΄λ¦¬ν μ μμ΅λλ€.
- λΆμ λ° λͺ¨λν°λ§: μ¬μ©μκ° μ ν리μΌμ΄μ μ μ½ν μΈ λ₯Ό 곡μ νλ λ°©λ²μ λν ν΅μ°°λ ₯μ μ»κΈ° μν΄ κ³΅μ λμ κΈ°λ₯μ μ¬μ©λμ μΆμ ν©λλ€. μ΄λ₯Ό ν΅ν΄ κ°μ μμμ μλ³νκ³ κ³΅μ λμ νκ²½μ μ΅μ ννλ λ° λμμ΄ λ μ μμ΅λλ€.
νλ«νΌ κ° κ³ λ € μ¬ν
Web Share Target APIλ νλ«νΌ κ°μ μ€κ³λμμ§λ§ μΌλμ λμ΄μΌ ν λͺ κ°μ§ νλ«νΌλ³ κ³ λ € μ¬νμ΄ μμ μ μμ΅λλ€.
- Android: Androidμμ 곡μ μνΈλ λ§€μ° μ¬μ©μ μ μ κ°λ₯νλ©° μ¬μ©μμ κΈ°λ³Έ μ€μ μ λ°λΌ μ ν리μΌμ΄μ μ΄ κ³΅μ μνΈμ λ€λ₯Έ μμΉμ λνλ μ μμ΅λλ€.
- iOS: iOSμμ 곡μ μνΈλ μ¬μ©μ μ μκ° λ κ°λ₯νλ©° μ¬μ©μκ° μ΅κ·Όμ μ¬μ©νμ§ μμ κ²½μ° μ ν리μΌμ΄μ μ΄ νμ 곡μ μνΈμ λνλμ§ μμ μ μμ΅λλ€.
- λ°μ€ν¬ν±: λ°μ€ν¬ν± μ΄μ 체μ μμ 곡μ μνΈκ° λ€λ₯Ό μ μκ±°λ μ ν μ¬μ©ν μ μμ μ μμ΅λλ€.
λ€μν νλ«νΌμμ 곡μ λμ κΈ°λ₯μ ν μ€νΈνμ¬ μ λλ‘ μλνκ³ μΌκ΄λ μ¬μ©μ νκ²½μ μ 곡νλμ§ νμΈν©λλ€.
κ²°λ‘
κ°λ ₯νκ³ μμ ν νλ‘ νΈμλ 곡μ λμ νλ‘μΈμλ₯Ό ꡬμΆνλ κ²μ Web Share Target APIμ μ±λ₯μ νμ©νλ λ° νμμ μ λλ€. μ΄ κ°μ΄λμ μ€λͺ λ λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄λ©΄ μΉ μ ν리μΌμ΄μ μ μ½ν μΈ λ₯Ό 곡μ νκΈ° μν μννκ³ λ§€λ ₯μ μΈ μ¬μ©μ κ²½νμ λ§λ€ μ μμ΅λλ€. 보μμ μ°μ μνκ³ , λͺ¨λ λ€μ΄μ€λ λ°μ΄ν°μ μ ν¨μ±μ κ²μ¬νκ³ , μ¬μ©μμκ² λͺ νν νΌλλ°±μ μ 곡νλ κ²μ μμ§ λ§μμμ€. Web Share Target APIλ μ¬λ°λ₯΄κ² ꡬννλ©΄ PWAμ μ¬μ©μ μ΄μ 체μ μμ ν΅ν©μ ν¬κ² ν₯μμν€κ³ μ λ°μ μΈ μ μ©μ±μ ν₯μμν¬ μ μμ΅λλ€.